(make-actor :machine-actor) ; :required-services )

(in-actor :machine-actor)

(defvar *username* :in-actor :machine-actor "user")
(defvar *buddy-map* (make-hash))

(defstruct text-message from content)

(defclass chat-local-facade (remote-object) ())

(defmethod set-username (name)
  (setf *username* name)
  (start-im))

(defmethod talk (to text)
  (let ((buddy (gethash to *buddy-map*)))
    (if buddy
        (let ((message (make-text-message :from *username* :content text)))
          (if (receive buddy message :due-to (seconds 10))
              (format *screen-output* "~D sent to ~D" text to)
            (format *screen-output* "message: ~D timed out" text)))
      (format *screen-output* "unknown body:~D" to))))

(defclass chat-remote-facade (remote-object) ())

(defmethod receive (chat-remote-facade message)
  (format *screen-output* "~D: ~D" (text-message-from message) (text-message-content message)))

(defmethod get-username (chat-remote-facade)
  *username*)

(defvar *remote-facade* (make-instance 'chat-remote-facade))
(defvar *local-facade* (make-instance 'chat-local-facade))
(defvar *instant-messenger* "instant-messenger")

(publish-service *remote-facade* *instant-messenger*)

(when-discovered *instant-messenger*
                 (lambda (messenger)
                   (let ((name (chat-remote-facade-name messenger)))
                     (unless (gethash name *buddy-list*)
                       (setf (gethash name *buddy-list*) name)
                       (format *screen-output* "Added buddy: ~D" name)
                       (when-disconnected messenger (lambda ()
                                                      (format *screen-output* "Buddy offline: ~D" name)))
                       (when-reconnected messenger (lambda ()
                                                     (format *screen-output* "Buddy online: ~D" name)))))))

; (provided-services :machine-actor)

; (required-services :machine-actor)
                       
                       






